<template>
    <div class="main-container">
        <!--查询数据-->
        <div>
            <el-form :model="searchForm" :inline="true" v-show="searchShow" label-width="68px">
                <el-form-item label="角色名称">
                    <el-input v-model="searchForm.roleName" placeholder="请输入角色名称" clearable style="width: 180px"
                        @keyup.enter="handleSearch" />
                </el-form-item>
                <el-form-item label="角色标识">
                    <el-input v-model="searchForm.roleLable" placeholder="请输入角色标识" clearable style="width: 180px"
                        @keyup.enter="handleSearch" />
                </el-form-item>
                <el-form-item label="状态">
                    <el-select v-model="searchForm.status" placeholder="角色状态" clearable style="width: 120px">
                        <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label"
                            :value="dict.value" />
                    </el-select>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" :icon="Search" @click="handleSearch">搜索</el-button>
                    <el-button :icon="Refresh" @click="resetSearch">重置</el-button>
                </el-form-item>
            </el-form>
        </div>
        <!-- 按钮区域-- -------------------- -->
        <div class="button-container">
            <div>
                <el-button type="primary" plain :icon="Plus" @click="handleAdd"
                    v-hasPermi="['system:user:add']">新增</el-button>
                <el-button type="danger" plain :icon="Delete" :disabled="multiple" @click="handleDelete"
                    v-hasPermi="['system:user:remove']">删除</el-button>
            </div>
            <div>
                <el-tooltip effect="dark" :content="searchShow ? '隐藏搜索' : '显示搜索'" placement="top">
                    <el-button circle :icon="Search" @click="toggleSearch" />
                </el-tooltip>
                <el-tooltip effect="dark" content="刷新" placement="top">
                    <el-button circle :icon="Refresh" @click="refresh" />
                </el-tooltip>
            </div>
        </div>

        <!-- 表格区域-------------------  -----------------------      -->
        <div>
            <el-table :data="tableList" @selection-change="handleSelectionChange">
                <el-table-column type="selection" width="50" align="center" />
                <el-table-column label="角色编号" align="center" prop="id" />
                <el-table-column label="角色名称" align="center" prop="roleName" :show-overflow-tooltip="true" />
                <el-table-column label="角色标识" align="center" prop="roleLabel" :show-overflow-tooltip="true" />
                <el-table-column label="显示顺序" align="center" prop="sort" width="120" />
                <el-table-column label="状态" align="center" prop="status">
                    <template #default="scope">
                        <el-switch v-model="scope.row.status" :active-value='0' :inactive-value='1'
                            @change="handleStatusChange(scope.row)"></el-switch>
                    </template>
                </el-table-column>
                <el-table-column label="创建时间" align="center" width="160" prop="createTime" :formatter="formatDate">
                </el-table-column>
                <el-table-column label="操作" align="center" width="150" class-name="small-padding fixed-width">
                    <template #default="scope">
                        <el-tooltip effect="dark" content="修改" placement="top">
                            <el-button link type="primary" :icon="Edit" @click="handleUpdate(scope.row)"
                                v-hasPermi="['system:user:edit']"></el-button>
                        </el-tooltip>
                        <el-tooltip effect="dark" content="删除" placement="top" v-if="scope.row.id !== 1">
                            <el-button link type="primary" :icon="Delete" @click="handleDelete(scope.row)"
                                v-hasPermi="['system:user:remove']"></el-button>
                        </el-tooltip>
                        <el-tooltip effect="dark" content="权限分配" placement="top">
                            <el-button link type="primary" :icon="User" @click="handleAuthRole(scope.row)"
                                v-hasPermi="['system:user:edit']"></el-button>
                        </el-tooltip>
                    </template>
                </el-table-column>
            </el-table>
        </div>
        <!-- 分页 ------------------------------------- -->
        <div style="margin-top: 20px">
            <el-pagination v-model:current-page="searchForm.currentPage" v-model:page-size="searchForm.pageSize"
                :page-sizes="[10, 20, 50, 100]" background layout="->, jumper, total, sizes, prev, pager, next"
                :total="PageDataTotal" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
        </div>

        <!-- 添加或修改配置对话框---------------------------------------------------- -->
        <el-dialog :title="title" v-model="dialogFormVisible" width="600px" append-to-body>
            <el-form :model="form" :rules="rules" ref="ruleFormRef" label-width="80px">
                <el-form-item label="角色名称" prop="roleName">
                    <el-input v-model="form.roleName" placeholder="请输入角色名称" />
                </el-form-item>
                <el-form-item label="角色标识" prop="roleLabel">
                    <el-input v-model="form.roleLabel" placeholder="请输入角色标识" />
                </el-form-item>
                <el-form-item label="角色顺序" prop="roleSort">
                    <el-input-number v-model="form.sort" controls-position="right" :min="0" />
                </el-form-item>
                <el-form-item label="状态">
                    <el-radio-group v-model="form.status">
                        <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.value">{{ dict.label
                            }}</el-radio>
                    </el-radio-group>
                </el-form-item>
                <el-form-item label="菜单权限">
                    <el-tree-select v-model="form.menuIds" :data="menuOptions" multiple :render-after-expand="false" collapse-tags
                        show-checkbox check-strictly check-on-click-node style="width: 240px" />
                </el-form-item>
                <el-form-item label="备注">
                    <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
                </el-form-item>
            </el-form>
            <template #footer>
                <div class="dialog-footer">
                    <el-button type="primary" @click="onDialogFormConfirm">确 定</el-button>
                    <el-button @click="onDialogFormCancel">取 消</el-button>
                </div>
            </template>
        </el-dialog>

        <!-- 权限分配框--------------------------------------------------------------  -->
        <el-dialog v-model="transferVisible" title="权限分配" width="800">
           <div class="transfer">
            <div class="contaner">
                <!-- 左-->
                <div class="item">
                    <div class="title">
                        已分配权限
                    </div>
                    <div class="tree">
                        <el-tree
                            ref="treeRef"
                            :data="transData"
                            :props="transProps"
                            @node-click="transHandleNodeClick"
                            show-checkbox
                        />
                    </div>
                </div>
                <div class="transfercenter">
                    <!-- 中   -->
                    <div class="transbutton">
                        <el-button type="primary" :icon="ArrowLeft" @click="leftButtonClick"></el-button>
                        <el-button type="primary"><el-icon class="el-icon--right" @click="rightButtonClick"><ArrowRight /></el-icon></el-button>
                    </div>
                </div>
                <!-- 右  -->
                <div class="item">
                    <div class="title">
                        未分配权限
                    </div>
                    <div class="tree">
                        <el-tree
                            ref="treeRef1"
                            :data="transData1"
                            :props="transProps"
                            @node-click="transHandleNodeClick1"
                            show-checkbox
                        />
                    </div>
                </div>

            </div>
            <div>
                <div class="footer">
                    <el-button type="primary" @click="onDialogFormConfirmTransfer">确 定</el-button>
                    <el-button @click="onDialogFormCancelTransFer">取 消</el-button>
                </div>
            </div>
           </div>
        </el-dialog>



    </div>
</template>

<script setup lang="ts">
import { Search, Refresh, Plus, Delete, Edit, User, ArrowLeft, ArrowRight } from '@element-plus/icons-vue'
import { ref } from 'vue'
import { selectListRoleService, pageListService, addRoleService, getRoleAndmenuIds, updateRoleService, deleteRoleByIds, updateRoleStatusByIds, searchAuthAndNot } from '@/api/sys/role'
import { menuTreeselect } from '@/api/sys/menu'
import { ElMessage, ElMessageBox } from "element-plus"

// 日期格式化
const formatDate = (row, column) => {
    const date = new Date(row[column.property]);
    return formatDateString(date);
};

const formatDateString = (date) => {
    const year = date.getFullYear();
    const month = pad2(date.getMonth() + 1);
    const day = pad2(date.getDate());
    const hours = pad2(date.getHours());
    const minutes = pad2(date.getMinutes());
    const seconds = pad2(date.getSeconds());

    return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
};
const pad2 = (number) => {
    return (number < 10 ? '0' : '') + number
}
// 查询区域   -----------------------------------------------------
// 查询参数
const searchForm = ref({
    currentPage: 1,
    pageSize: 10,
})
// 是否显示
const searchShow = ref(true)
// 状态 0：可用， 1: 不可用
const sys_normal_disable = [
    {
        label: "可用",
        value: 0
    },
    {
        label: "不可用",
        value: 1
    }
]
// 重置查询表单
const resetSearch = () => {
    searchForm.value.currentPage = searchForm.value.currentPage
    searchForm.value.pageSize = searchForm.value.pageSize
    searchForm.value.status = ''
    getPageList()
}
// 查询事件
const handleSearch = () => {
    getPageList()
}

// 操作按钮区域----------------------------------------------------------------
// 操作区显示隐藏控制
const toggleSearch = () => {
    // console.log("toggleSearch--------------search.valeue", searchShow.value)
    if (searchShow.value) {
        searchShow.value = false
        return
    }
    searchShow.value = true
}
// 刷新
const refresh = () => {
    getPageList()
}
// 添加
const handleAdd = () => {
    getMenuTreeselect()
    title.value = addTite
    isAdd.value = true
    dialogFormVisible.value = true
}

// 修改
const handleUpdate = async (row) => {
    getMenuTreeselect()
    const roleId = row.id
    console.log("handleUpdate", id)
    title.value = updateTite
    isAdd.value = false
    let result = await getRoleAndmenuIds(roleId)
    form.value = result.data
    dialogFormVisible.value = true
}
/** 删除按钮操作 */
const handleDelete = (row) => {
    const roleIds = [row.id] || ids.value;
    ElMessageBox.confirm('确认要删除吗？', '提示',
        {
            confirmButtonText: '确认',
            cancelButtonText: '取消',
            type: 'warning',
        }
    ).then(async () => {
        // 删除
        console.log("delete===== ids", roleIds)
        let result = await deleteRoleByIds(roleIds)
        if (result.code == 0) {
            ElMessage.success(result.msg ? result.msg : '删除成功')
            getPageList()
        } else {
            ElMessage.error(result.msg ? result.msg : '删除失败')
        }
    }).catch(() => { })
}
const handleImport = () => {

}
const handleExport = () => {

}

// 分页----------------------------------------------------------
// 分页数据总条数
const PageDataTotal = ref(0)
// 分页插件，每页条数发生改变时
const handleSizeChange = (val) => {
    searchForm.value.pageSize = val
    getPageList()
}
// 分页插件， 当页码发生改变时
const handleCurrentChange = (val) => {
    searchForm.value.currentPage = val
    getPageList()
}

// 分页查询
const getPageList = async () => {
    //console.log("getPageList:===", searchForm.value)
    //console.log("getPageList status===", searchForm.value.status)
    let param = JSON.parse(JSON.stringify(searchForm.value))
    if (searchForm.value.status === undefined || searchForm.value.status == '') {
        param.status = -1;
    }
    try {
        const result = await pageListService(param)
        PageDataTotal.value = result.data.total;
        tableList.value = result.data.list;
    } catch (err) { }
    //console.log("tableData:", tableData);
}
getPageList()


// 表格区域----------------------------------------------------------------
// 表格数据
const tableList = ref()
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
// 列显隐信息
const columns = ref([
    { key: 0, label: `用户编号`, visible: true },
    { key: 1, label: `用户名称`, visible: true },
    { key: 2, label: `用户昵称`, visible: true },
    { key: 3, label: `手机号码`, visible: true },
    { key: 4, label: `状态`, visible: true },
    { key: 5, label: `创建时间`, visible: true }
]);
/** 选择条数  */
const handleSelectionChange = (selection) => {
    ids.value = selection.map(item => item.id);
    single.value = selection.length != 1;
    multiple.value = !selection.length;
}
// /** 角色状态修改  */
const handleStatusChange = (row) => {
    let text = row.status === 0 ? "启用" : "停用"
    let roleId = row.id
    ElMessageBox.confirm('确认要' + text + row.roleName + '角色吗？', '提示',
        {
            confirmButtonText: '确认',
            cancelButtonText: '取消',
            type: 'warning',
        }
    ).then(async () => {
        let param = {
            roleId: row.id,
            status: row.status
        }
        let result = await updateRoleStatusByIds(param)
        // console.log("status result :==", result)
        if (result.code == 0) {
            ElMessage.success(result.message ? result.message : '操作成功')
            getPageList()
        } else {
            ElMessage.error(result.message ? result.message : '操作失败')
        }
    }).catch(() => { 
        getPageList()
    })
}

// 重置密码
const handleResetPwd = (row) => {
    dialogFormVisiblepass.value = true;
    formpass.value.id = row.id;
}
// 权限分配
const handleAuthRole = async (row: any) => {
    roleId = row.id
   try {
    let result = await searchAuthAndNot(row.id)
    transData.value = result.data.auth
    transData1.value = result.data.notAuth
   } catch (e) {}
    transferVisible.value = true
}

/** 添加修改相关表单----------------------------------------- */
// 角色树
const menuOptions = ref();

// 角色下拉选择数据
const roleOptions = ref()
const form = ref({})
let addTite = "添加角色"
let updateTite = "修改角色"
const title = ref(addTite)
const isAdd = ref(true)
const dialogFormVisible = ref(false)

// 重置对话框表单
const restForm = () => {
    form.value = {}
    title.value = addTite
    isAdd.value = true
}

// 提交对话框表单按钮事件
const onDialogFormConfirm = async () => {
    //1.验证表单
    if (!ruleFormRef.value) return
    //2.提交表单
    await ruleFormRef.value.validate((valid) => {
        if (valid) {    // 校验成功
            confirm()
        }
    })
}
// 取消对话表单框按钮事件
const onDialogFormCancel = () => {
    console.log("cancel......")
    dialogFormVisible.value = false
    restForm()
}

// 查询角色列表
const searchRole = async () => {
    try {
        let result = await selectListRoleService()
        roleOptions.value = result.data;
    } catch (e) { }
}

/** 查询菜单树结构 */
const getMenuTreeselect = async () => {
    try {
        let result = await menuTreeselect()
        console.log("getMenuTreeselect", result.data)
        menuOptions.value = result.data;
        console.log("getMenuTreeselect  value", menuOptions.value)
    } catch (e) { }
}

// 提交表单
const confirm = async () => {
    console.log("confirm-------")
    if (isAdd.value) {
        console.log("confirm-add------")
        // 添加
        try {   // 添加成功
            let result = await addRoleService(form.value)
            ElMessage.success(result.msg ? result.msg : '添加成功')
            // 关闭弹窗，清空表单
            dialogFormVisible.value = false
            restForm()
            getPageList()
            console.log("result-------")
        } catch (error) { }
    } else {
        console.log("update=======")
        //修改
        try {   // 修改成功
            let result = await updateRoleService(form.value)
            ElMessage.success(result.msg ? result.msg : '修改成功')
            // 关闭弹窗，清空表单
            dialogFormVisible.value = false
            restForm()
            getPageList()
        } catch (error) { }
    }

}

/** 表单校验 */
const ruleFormRef = ref(null)   // 定义表单组件的引用
const rules = ref({
    roleName: [{ required: true, message: "角色名不能为空", trigger: "blur" }, { min: 2, max: 20, message: "用户名称长度必须介于 2 和 20 之间", trigger: "blur" }],
    roleLabel: [{ required: true, message: "角色标识不能为空", trigger: "blur" }],
    status: [{ required: true, message: "角色状态不能为空", trigger: "blur" }, { min: 5, max: 20, message: "用户密码长度必须介于 5 和 20 之间", trigger: "blur" }, { pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符：< > \" ' \\\ |", trigger: "blur" }],
})

// 权限分配------------------------------------------
let roleId: number = -1
const transferVisible = ref(false)
const transData = ref()
const transData1 = ref()
const treeRef = ref() 
const treeRef1= ref() 
const transProps = {
    id: "roleId",
    children: 'children',
    label: 'menuName',
}

// 提交对话框表单按钮事件
const onDialogFormConfirmTransfer = async () => {
    let authMenus = flattenMenuTree(transData.value)
    let ids = authMenus.map(item => item.id)
    let params = {
        roleId: roleId,
        menuIds: ids
    }
    console.log("params:", params)
    let result = await updateRoleService(params)
    ElMessage.success(result.msg ? result.msg : '修改成功')
            // 关闭弹窗，清空表单
            transferVisible.value = false


}
// 取消对话表单框按钮事件
const onDialogFormCancelTransFer = () => {
    transferVisible.value = false
}

// 授权按钮
const leftButtonClick = () => {
    //console.log(treeRef1.value.getCheckedNodes(false, false))
    let selctedMenus = treeRef1.value.getCheckedNodes(false, false)
    let ids = selctedMenus.map(item => item.id)
    // 解构菜单树
    let authList = flattenMenuTree(transData.value)
    let notAuthList = flattenMenuTree(transData1.value)
    //console.log("authList: " + authList)
    //console.log("notauthList: " + notAuthList)
    // 添加授权，删除未授权菜单
    authList.push(...selctedMenus)
    notAuthList = notAuthList.filter(item => !ids.includes(item.id))
    //console.log("authList: ",authList)
    //console.log("notauthList: " + notAuthList)
    // 重新构建菜单树
    transData.value = []
    transData1.value = []
    // authList = filterRepetition(authList)
    // notAuthList = filterRepetition(notAuthList)
    transData.value = buildMenuTree(filterRepetition(authList))
    //console.log("transData:", transData.value)
    transData1.value = buildMenuTree(filterRepetition(notAuthList))
}

// 取消授权按钮
const rightButtonClick = () => {
    let selctedMenus = treeRef.value.getCheckedNodes(false, false)
    let ids = selctedMenus.map(item => item.id)
    // 解构菜单树
    let authList = flattenMenuTree(transData.value)
    let notAuthList = flattenMenuTree(transData1.value)
    // 添加授权，删除未授权菜单
    notAuthList.push(...selctedMenus)
    authList = authList.filter(item => !ids.includes(item.id))
    // 重新构建菜单树
    transData.value = buildMenuTree(filterRepetition(authList))
    transData1.value = buildMenuTree(filterRepetition(notAuthList))
}

// 构建列表树
function buildMenuTree(menuList) {  
    // 创建一个映射，以便快速通过ID查找菜单项  
    const map = new Map(menuList.map(item => [item.id, { ...item, children: [] }]));  
  
    // 遍历菜单列表，构建树结构  
    function attachChildren(parentId = 0) {  
        // 查找所有具有指定parentId的菜单项  
        return menuList.filter(item => item.parentId === parentId).map(item => {  
            const currentNode = map.get(item.id);  
            // 递归地为当前节点附加子节点  
            currentNode.children = attachChildren(item.id);  
            return currentNode;  
        });  
    }  
  
    // 注意：顶级菜单项（没有parentId或parentId为null/undefined）  
    const tree = attachChildren();  
    return tree;  
} 

function flattenMenuTree(tree) {  
    let result = [];  
    // 递归函数来遍历树并收集节点  
    function traverse(nodes) {  
        nodes.forEach(node => {  
            // 将当前节点添加到结果数组中  
            result.push({ ...node});
            if (node.children && node.children.length > 0) {  
                traverse(node.children);
            }  
        });  
    }    
    // 开始遍历树  
    traverse(tree);  
  
    // 如果不需要层级信息，直接返回结果数组  
    return result;  
}  

// 过滤重复的菜单
const filterRepetition = (menulist) => {
    // console.log("menulist: " + menulist)
    let seenIds = new Set();  
    // 过滤菜单项  
    let menus = menulist.filter(item => {  
        // 如果当前项的id在Set中不存在，则添加到Set中，并返回true（保留该项）  
        // 否则，返回false（移除该项）  
        if (!seenIds.has(item.id)) {  
            seenIds.add(item.id);  
            return true;  
        }  
        return false;  
    })
    //console.log("menulist: " + menulist)
    return menus
}




</script>
<style lang="scss" >
    .transfer {
        display: flex;
        flex-direction: column;
        .contaner {
            display: flex;
            flex-direction: row;
            justify-content: space-between;
            height: 500px;
            .item {
                display: flex;
                flex-direction: column;
                width: 40%;
                height: 100%;
                .title {
                    text-align: center;
                    background-color: #F5F7FA;
                    height: 6%;
                    font-size: 16px;

                }
                .tree {
                    overflow-y: scroll;
                    height: 94%;
                }
            }
            .transfercenter {
                display: flex;
               
               padding-top: 30px;
               box-sizing: border-box;
                width: 20%;
                height: 100%;
                // border: 10px solid black; /* 边框宽度、样式、颜色 */
                // background-color: #FF0000;
                .transbutton {
                    margin-top: 200px;
                }
                    
            }
           
          
        }
        .footer {
            display: flex;
            flex-direction: row;
            justify-content: center;
            align-items: center;
        }
    }
   
</style>